package root.electronclass.electronclass.grade.homework

import android.annotation.SuppressLint
import android.content.res.ColorStateList
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.EditText
import android.widget.TextView
import androidx.appcompat.widget.ListPopupWindow
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.text.bold
import androidx.core.text.buildSpannedString
import androidx.core.view.forEachIndexed
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.lifecycle.lifecycleScope
import root.electronclass.electronclass.common.base.BasicAdapter
import root.electronclass.electronclass.common.base.ViewBindingFragment
import root.electronclass.electronclass.common.util.ToastUtil
import root.electronclass.electronclass.R
import root.electronclass.electronclass.databinding.FragmentClassHomeworkSubmitBinding
import root.electronclass.electronclass.databinding.FragmentClassHomeworkSubmitItemBinding
import root.electronclass.electronclass.databinding.FragmentClassHomeworkSubmitMultiItemBinding
import root.electronclass.electronclass.ext.CoroutineExceptionHandler
import root.electronclass.electronclass.ext.doOnTabSelected
import root.electronclass.electronclass.ext.dp
import root.electronclass.electronclass.grade.model.ClassHomeworkDepart
import root.electronclass.electronclass.grade.model.ClassHomeworkItem
import root.electronclass.electronclass.grade.model.ClassHomeworkUser
import root.electronclass.electronclass.grade.model.ClassSubmitHomework2
import root.electronclass.electronclass.grade.model.ClassSubmitHomeworkSubject
import root.electronclass.electronclass.grade.model.PersonType
import root.electronclass.electronclass.mvp.GlobalParameter
import root.electronclass.electronclass.mvp.base.data
import root.electronclass.electronclass.mvp.base.isActionSuccessful
import root.electronclass.electronclass.mvp.base.isSuccessful
import root.electronclass.electronclass.mvp.entity.ApiException
import root.electronclass.electronclass.mvp.rest.ClassApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.withContext
import java.math.BigDecimal
import java.text.DecimalFormat
import kotlin.collections.set

/**
 * 作业提交
 * @author Lokiy
 * @date 2023/3/29 23:40
 */
class ClassSubmitHomeworkFragment : ViewBindingFragment<FragmentClassHomeworkSubmitBinding>() {

    private lateinit var detail: ClassHomeworkItem
    private lateinit var submitData: ClassSubmitHomework2
    private var selectSubjectId: Long = 0L
    private val subjectList: MutableList<ClassSubmitHomeworkSubject> = mutableListOf()
    private val df = DecimalFormat("0.#")
    private var subjectType: Int = 1 //1-单科提交 2-多科提交
    private var submitPersonType: Int = 1 //1-个人提交, 2班级提交
    private var onSubmit = false//发起提交
    private val mutex = Mutex()
    private val homeworkCacheMap = HashMap<String, ClassSubmitHomework2>()
    private val personType = GlobalParameter.getPersonLoginResult()?.personType

    private val studentAdapter = BasicAdapter<ClassHomeworkUser, FragmentClassHomeworkSubmitItemBinding>(onViewRecycled = {
        it.binding.itemElapsed.clearTextWatcher()
        it.binding.itemComment.clearTextWatcher()
        it.binding.itemElapsed.setText("")
        it.binding.itemComment.setText("")
    }) { holder, item ->
        holder.binding.root.setBackgroundResource(if (holder.adapterPosition % 2 == 0) 0 else R.drawable.bg_306eff_8)
        holder.binding.root.backgroundTintList = ColorStateList.valueOf(0x15306eff)

        holder.binding.itemName.text = item.name
        holder.binding.itemNo.text = item.userNo

        holder.binding.itemElapsed.setText(if (item.hour != null) df.format(item.hour) else "")
        holder.binding.itemComment.setText(item.comment ?: "")

        holder.binding.itemElapsed.doAfterTextChanged {
            if (numberTextWatcher(holder.binding.itemElapsed) && it.toString() != ".") {
                item.hour = BigDecimal(it.toString().trim().ifEmpty { "0" }).toFloat()
            }
        }
        holder.binding.itemComment.doAfterTextChanged {
            item.comment = it.toString().trim()
        }
        if (onSubmit) {
            if (item.hour == null || item.hour == 0f) {
                holder.binding.itemElapsed.error = "请输入作业耗时"
            } else {
                holder.binding.itemElapsed.error = null
            }

            if (item.comment.isNullOrEmpty()) {
                holder.binding.itemComment.error = "请输入评价内容"
            } else {
                holder.binding.itemComment.error = null
            }
        }
    }

    private val multiAdapter = BasicAdapter<ClassHomeworkDepart, FragmentClassHomeworkSubmitMultiItemBinding>(onViewRecycled = {
        it.binding.itemElapsed.clearTextWatcher()
        it.binding.itemComment.clearTextWatcher()
        it.binding.itemElapsed.setText("")
        it.binding.itemComment.setText("")
        it.binding.itemFinishFlag.onCheckedChangeListener = null
    }) { holder, item ->
        holder.binding.root.setBackgroundResource(if (holder.adapterPosition % 2 == 0) 0 else R.drawable.bg_306eff_8)
        holder.binding.root.backgroundTintList = ColorStateList.valueOf(0x15306eff)

        holder.binding.itemName.text = item.subjectName
        holder.binding.itemFinishFlag.isChecked = item.finishFlag == 1
        holder.binding.itemFinishFlag.onCheckedChangeListener = { isChecked ->
            item.finishFlag = if (isChecked) 1 else 2
        }

        holder.binding.itemElapsed.setText(if (item.hour != null) df.format(item.hour) else "")
        holder.binding.itemComment.setText(item.comment ?: "")

        holder.binding.itemElapsed.doAfterTextChanged {
            if (numberTextWatcher(holder.binding.itemElapsed) && it.toString() != ".") {
                item.hour = BigDecimal(it.toString().trim().ifEmpty { "0" }).toFloat()
            }
        }
        holder.binding.itemComment.doAfterTextChanged {
            item.comment = it.toString().trim()
        }
        if (onSubmit) {
            if (item.hour == null || item.hour == 0f) {
                holder.binding.itemElapsed.error = "请输入作业耗时"
            } else {
                holder.binding.itemElapsed.error = null
            }

//            if (item.comment.isNullOrEmpty()) {
//                holder.binding.itemComment.error = "请输入评价内容"
//            } else {
//                holder.binding.itemComment.error = null
//            }
        }
    }

    @SuppressLint("NotifyDataSetChanged")
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        val homeworkItem = arguments?.getParcelable<ClassHomeworkItem>(ClassHomeworkDetailDialog.DATA)?.also { detail = it }
        val padding = 24.dp.toInt()
        if (homeworkItem != null) {
            //有选中作业
            binding.detail.update(homeworkItem)
            binding.detail.root.let {
                it.setBackgroundResource(R.drawable.bg_white_12)
                it.setPadding(32, padding, 32, padding)
                it.updateLayoutParams<ViewGroup.LayoutParams> {
                    width = 375.dp.toInt()
                }
            }
            showHomeworkDetailLayout()
        } else {
            binding.detail.root.isVisible = false
        }
        binding.tabLayout.apply {
            arrayOf("个人提交", "班级提交").forEach {
                addTab(newTab().setText(it))
            }
            doOnTabSelected {
                submitPersonType = if (it?.position == 0) 1 else 2
                if (personType == PersonType.CLASS_LEADER || personType == PersonType.TEACHER) {
                    binding.viewSwitcher.showNext()
                    getData()
                } else if (it?.position == 1) {
                    ToastUtil.showToast(requireContext(), "仅班干部可班级提交")
                }
            }
        }
        binding.submitTypeGroup.check(R.id.submitGroupSingle)
        binding.submitTypeGroup.setOnCheckedChangeListener { group, checkedId ->
            subjectType = if (checkedId == R.id.submitGroupSingle) 1 else 2
            getData()
        }
        when (personType) {
            PersonType.CLASS_LEADER -> {
            }

            PersonType.TEACHER -> {
                binding.tabLayout.isVisible = false
                submitPersonType = 2
                binding.viewSwitcher.showNext()
            }

            else -> {
                binding.tabLayout.isEnabled = false
                binding.tips.isVisible = true
            }
        }
        initPersonalSubmit()
        initCollectionSubmit(padding)
        binding.cancel.setOnClickListener {
            requireActivity().finish()
        }
        binding.submit.setOnClickListener {
            if (this@ClassSubmitHomeworkFragment::detail.isInitialized.not() && subjectType == 1 && selectSubjectId == 0L) {
                return@setOnClickListener toast("请选择一个科目")
            }
            if (this::submitData.isInitialized.not()) {
                toast("作业信息初始化失败，请稍后重试")
                getData()
                return@setOnClickListener
            }
            if (submitPersonType == 1) {
                //个人提交
                if (subjectType == 1) {
                    //单科提交
                    val elapsed =
                        binding.editText.text.toString().trim()
                            .let { if (it.endsWith(".")) it.substring(0, it.length - 1) else it }
                            .ifEmpty { return@setOnClickListener ToastUtil.showToast(requireActivity(), "请输入作业耗时") }
                    val elapsedHour = runCatching {
                        val toFloat = BigDecimal((elapsed).ifEmpty { "0" }.replaceMoreDot()).toFloat()
                        if (toFloat == 0f) {
                            return@setOnClickListener ToastUtil.showToast(requireActivity(), "请输入作业耗时")
                        }
                        toFloat
                    }.onFailure {
                        return@setOnClickListener ToastUtil.showToast(requireActivity(), "请输入正确的作业耗时")
                    }.getOrDefault(1f)

                    val comment = binding.comment.text.toString().trim()
                        .ifEmpty { return@setOnClickListener ToastUtil.showToast(requireActivity(), "请输入评价内容（难易、数量等）") }
                    //提交个人作业
                    submitData.person?.apply {
                        this.comment = comment
                        this.hour = elapsedHour
                    }
                    submitHomework()
                } else {
                    //多科提交
                    onSubmit = true
                    if ((submitData.personList?.count { it.hour == null || it.hour == 0f /*|| it.comment.isNullOrEmpty()*/ } ?: 0) > 0) {
                        studentAdapter.notifyDataSetChanged()
                    } else {
                        //提交集体作业
                        submitHomework()
                    }
                }
            } else {
                //班级提交
                if (subjectType == 1) {
                    //单科提交
                    onSubmit = true
                    if ((submitData.list?.count { it.hour == null || it.hour == 0f || it.comment.isNullOrEmpty() } ?: 0) > 0) {
                        studentAdapter.notifyDataSetChanged()
                    } else {
                        submitHomework()
                    }
                } else {
                    //多科提交
                    onSubmit = true
                    if ((submitData.list2?.count { it.hour == null || it.hour == 0f/* || it.comment.isNullOrEmpty()*/ } ?: 0) > 0) {
                        studentAdapter.notifyDataSetChanged()
                    } else {
                        submitHomework()
                    }
                }
            }
        }
        val onSubjectClick: (v: View) -> Unit = click@{
            if (subjectList.isEmpty()) return@click
            ListPopupWindow(requireContext()).apply {
                anchorView = it
                isModal = true
                setAdapter(ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, subjectList.map { it.subjectName }))
                setOnItemClickListener { _, _, position, _ ->
                    selectSubjectId = subjectList.getOrNull(position)?.id ?: 0
                    binding.subjectTotal.text = subjectList.getOrNull(position)?.subjectName
                    binding.subjectPersonal.text = subjectList.getOrNull(position)?.subjectName
                    getData()
                    dismiss()
                }
            }.show()

        }
        binding.subjectTotal.setOnClickListener(onSubjectClick)
        binding.subjectPersonal.setOnClickListener(onSubjectClick)

        getData()
    }

    //有传进来作业详情
    private fun showHomeworkDetailLayout() {
        binding.submitTypeGroup.isVisible = false
        binding.submitTypeTips.isVisible = false
        binding.subjectPersonal.isVisible = false
        binding.subjectPersonalTitle.isVisible = false
        binding.subjectPersonalArrow.isVisible = false

        binding.multiSubjectTitle.root.isVisible = false
        binding.multiSubjectRecycler.isVisible = false
        binding.submitGroupMulti.isVisible = false
        (binding.studentRecycler.parent as View).updateLayoutParams<ViewGroup.MarginLayoutParams> {
            topMargin = 40
        }
        binding.userName.updateLayoutParams<ViewGroup.MarginLayoutParams> {
            topMargin = 174
        }
    }

    //没有传进来作业详情
    private fun initMultiView(personType: PersonType?) {
        if (this::detail.isInitialized) {
            binding.userName.isVisible = submitPersonType == 1 && personType != PersonType.TEACHER
            binding.no.isVisible = submitPersonType == 1 && personType != PersonType.TEACHER
            return//有作业详情直接return
        }
        binding.userName.updateLayoutParams<ViewGroup.MarginLayoutParams> {
            topMargin = if (submitPersonType == 1 && subjectType == 1) 174 else 128
        }
        binding.submitTypeTips.updateLayoutParams<ViewGroup.MarginLayoutParams> {
            topMargin = if (submitPersonType == 1 && subjectType == 1) 174 else 128
            marginStart = when (submitPersonType) {
                1 -> 980
                else -> when (subjectType) {
                    1 -> 394
                    else -> 708
                }
            }
        }
        //名字和学号，只有个人提交的时候才会显示
        binding.userName.isVisible = submitPersonType == 1 && personType != PersonType.TEACHER
        binding.no.isVisible = submitPersonType == 1 && personType != PersonType.TEACHER

        binding.subjectTotal.isVisible = submitPersonType != 1 && subjectType == 1
        binding.subjectTotalTitle.isVisible = submitPersonType != 1 && subjectType == 1
        binding.subjectTotalArrow.isVisible = submitPersonType != 1 && subjectType == 1

        binding.multiSubjectRecycler.isVisible = subjectType == 2
        binding.multiSubjectTitle.root.isVisible = subjectType == 2

        if (subjectType == 2) {
            //多科
            binding.multiSubjectTitle.root.apply {
                val names =
                    resources.getStringArray(if (submitPersonType == 1) R.array.class_homework_submit_multi_self_titles else R.array.class_homework_submit_multi_all_titles)
                forEachIndexed { index, it ->
                    val view1: View
                    if (it is TextView) {
                        view1 = it
                    } else {
                        it as ViewGroup
                        view1 = it.getChildAt(0)
                        view1 as TextView
                    }
                    view1.setTextColor(0xFFFFFFFF.toInt())
                    view1.text = names[index]
                }
                setBackgroundResource(R.drawable.bg_306eff_round)
                backgroundTintList = resources.getColorStateList(R.color.c_brand_20, null)
            }
        }
    }

    private fun initPersonalSubmit() {
        binding.userName.text = buildSpannedString {
            bold { append("姓名：") }
            append(GlobalParameter.getPersonLoginResult()?.name ?: "")
        }
        binding.no.text = buildSpannedString {
            bold { append("学号：") }
            append(GlobalParameter.getPersonLoginResult()?.userNo ?: "")
        }
        binding.editText.doAfterTextChanged {
            numberTextWatcher(binding.editText)
        }
        binding.add.setOnClickListener {
            val bigDecimal = BigDecimal(binding.editText.text.toString().ifEmpty { "0" }.replaceMoreDot())
            binding.editText.setText(df.format(bigDecimal.add(BigDecimal("1").coerceAtMost(BigDecimal("9999")))))
            binding.editText.setSelection(binding.editText.text.toString().length)
        }
        binding.sub.setOnClickListener {
            val bigDecimal = BigDecimal(binding.editText.text.toString().ifEmpty { "0" }.replaceMoreDot())
            binding.editText.setText(df.format(bigDecimal.add(BigDecimal("-1")).coerceAtLeast(BigDecimal("0"))))
            binding.editText.setSelection(binding.editText.text.toString().length)
        }
    }

    private fun numberTextWatcher(editText: EditText): Boolean {
        val text = editText.text.toString()
        return if (text.endsWith(".") && text.count { it == '.' } > 1) {
            editText.setText(text.substring(0, text.length - 1))
            editText.setSelection(editText.text.toString().length)
            false
        } else {
            val indexOfFirst = text.indexOfFirst { it == '.' }
            if (indexOfFirst >= 0 && text.length - indexOfFirst > 2) {
                editText.setText(text.substring(0, indexOfFirst + 2))
                editText.setSelection(editText.text.toString().length)
                false
            } else if (text != text.replaceMoreDot()) {
                editText.setText(text.replaceMoreDot())
                editText.setSelection(editText.text.toString().length)
                false
            } else {
                true
            }
        }
    }

    private fun initCollectionSubmit(padding: Int) {
        binding.studentRecyclerTitle.root.apply {
            val names = resources.getStringArray(R.array.class_homework_submit_titles)
            forEachIndexed { index, it ->
                val view1: View
                if (it is TextView) {
                    view1 = it
                } else {
                    it as ViewGroup
                    view1 = it.getChildAt(0)
                    view1 as TextView
                }
                view1.text = names[index]
            }
            setBackgroundResource(R.drawable.bg_306eff_round)
            backgroundTintList = resources.getColorStateList(R.color.c_brand_20, null)
            updateLayoutParams<ConstraintLayout.LayoutParams> {
                topMargin = padding
            }
        }
        binding.studentRecycler.adapter = studentAdapter
        binding.multiSubjectRecycler.adapter = multiAdapter
        binding.studentRecycler.let {
            it.itemAnimator?.apply {
                addDuration = 0
                addDuration = 0
                moveDuration = 0
                removeDuration = 0
            }
        }
        binding.multiSubjectRecycler.let {
            it.itemAnimator?.apply {
                addDuration = 0
                addDuration = 0
                moveDuration = 0
                removeDuration = 0
            }
        }
    }

    private fun submitHomework() {
        submitData.type = submitPersonType
        submitData.subjectType = subjectType
        lifecycleScope.launch(CoroutineExceptionHandler()) {
            val result = withContext(Dispatchers.IO) {
                ClassApi.service.submitHomework2(submitData)
            }
            if (result.isActionSuccessful) {
                toast("提交成功")
                requireActivity().finish()
            } else {
                throw ApiException(result?.code ?: -1, result?.msg)
            }
        }
    }

    private fun getData() {
        initMultiView(personType)
        onSubmit = false
        //detail 可能为空
        if (this::detail.isInitialized) {
            lifecycleScope.launch(CoroutineExceptionHandler()) {
                val key = "${detail.id}-${selectSubjectId}-${subjectType}-${submitPersonType}"
                submitData = homeworkCacheMap[key] ?: withContext(Dispatchers.IO) {
                    ClassApi.service.submitHomeworkDetail2(detail.id, subjectType = subjectType, type = submitPersonType).data
                        .also { homeworkCacheMap[key] = it }
                }
                fillData()
            }
        } else {
            //没有选中作业进入的情况下
            lifecycleScope.launch(CoroutineExceptionHandler {
                mutex.unlock()
            }) {
                mutex.lock()
                val cacheKey = "0-${selectSubjectId}-${subjectType}-${submitPersonType}"
                if (subjectType == 1) {
                    //单科提交
                    if (subjectList.isEmpty()) {
                        //未获取科目列表，需要先获取科目列表
                        val result = withContext(Dispatchers.IO) {
                            ClassApi.service.submitHomeworkSubjectList()
                        }
                        if (result.isSuccessful) {
                            subjectList.clear()
                            subjectList += result.data
                        }
                    } else if (selectSubjectId != 0L) {
                        //获取作业详情
                        //单科个人
                        submitData = homeworkCacheMap[cacheKey] ?: withContext(Dispatchers.IO) {
                            ClassApi.service.submitHomeworkDetail2(null, selectSubjectId, subjectType, submitPersonType).data
                                .also { homeworkCacheMap[cacheKey] = it }
                        }
                        fillData()
                    } else {
                        Log.e("XXX", "未选择科目！！！")
                    }
                } else {
                    //多科提交
                    submitData = homeworkCacheMap[cacheKey] ?: withContext(Dispatchers.IO) {
                        ClassApi.service.submitHomeworkDetail2(null, null, subjectType, submitPersonType).data
                            .also { homeworkCacheMap[cacheKey] = it }
                    }
                    fillData()
                }
                mutex.unlock()
            }
        }
    }

    private fun fillData() {
        if (subjectType == 1) {
            studentAdapter.refresh(submitData.list)
            val format = df.format(BigDecimal(submitData.person?.hour?.toString()?.ifEmpty { "0" } ?: "0"))
            binding.editText.setText(if (format == "0") "" else format)
            binding.comment.setText(submitData.person?.comment ?: "")
        } else {
            if (submitPersonType == 1) {
                //多科个人
                multiAdapter.refresh(submitData.personList)
            } else {
                //多科班级
                multiAdapter.refresh(submitData.list2)
            }
        }
    }

    private fun String.replaceMoreDot(): String {
        var result = this
        while (result.count { it == '.' } > 1) {
            result = result.replaceFirst(".", "")
        }
        return result
    }

    private inline fun TextView.doAfterTextChanged(
        crossinline action: (text: Editable?) -> Unit
    ) {
        addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            }

            override fun afterTextChanged(s: Editable?) {
                action.invoke(s)
            }

        }.also { setTag(R.id.item_tag, it) })
    }

    private fun TextView.clearTextWatcher() {
        val tag = getTag(R.id.item_tag)
        if (tag is TextWatcher) {
            removeTextChangedListener(tag)
        }
    }
}